package be.xios.projectquiz.database;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import net.miginfocom.swing.MigLayout;

/// <summary>
/// Deze klasse is de GUI om een backup te nemen
/// </summary>
/// <author>Flemming Bosch</author>
public class BackupGUI extends JFrame{
	private static final long serialVersionUID = 1L;
	//Panels
	private JPanel getData;
	private JPanel backup;

		//Labels
		private JLabel lblUname;
		private JLabel lblPasswd;
		private JLabel lblDburl;
		private JLabel lblDbPort;
		private JLabel lblDb;
		private JLabel lblBackupTo;
		
		//Textfields
		private JTextField username;
		private JTextField password;
		private JTextField databaseUrl;
		private JTextField databasePort;
		private JTextField backupTo;
		
		//Buttons
		private JButton chooseBtn;
		private JButton retrieveDbBtn;
		private JButton backupBtn;
		
		//JCombobox
		private JComboBox<String> cb;
		
		//Variabelen
		private List<String> databasesAL = new ArrayList<String>();
		private String[] linesArr;
		private int counter=0;
		private String SelectedDatabaseName;
		private Connection con = null;
	
	/// <summary>
	/// Dit is de default constructor waar de GUI word in aangemaakt.
	/// </summary>
	/// <author>Flemming Bosch</author>
	public BackupGUI(){
		super("Backup Tool - MySQL Databases");
		
			//TopPanel 
			getData = new JPanel(new MigLayout());
			getData.setBorder(new TitledBorder(""));
			
				//Labels aanmaken
				lblUname = new JLabel("Gebruikersnaam ");
				lblPasswd = new JLabel("Wachtwoord ");
				lblDburl = new JLabel("Database URL/Host ");
				lblDbPort = new JLabel("Database Poort ");
				lblDb = new JLabel("Database ");
				lblBackupTo = new JLabel("Backup naar ");
				lblBackupTo.setEnabled(false);
				lblDb.setEnabled(false);
				
				//Textfields aanmaken
				username = new JTextField(15);
				password = new JTextField(15);
				databaseUrl = new JTextField(15);
				databasePort = new JTextField("3306",5);
				backupTo = new JTextField(15);
				backupTo.setEnabled(false);
				
				//Jcombobox aanmaken
				cb = new JComboBox<String>();
				cb.setMaximumRowCount(5);
				cb.addItemListener(new ItemListener() {
					@Override
					public void itemStateChanged(ItemEvent arg0) {
						if(arg0.getStateChange() == ItemEvent.SELECTED){
							SelectedDatabaseName = (String)cb.getSelectedItem();
						}	
					}
				});
				
				
				//Buttons aanmaken
				chooseBtn = new JButton("Kies opslagplaats");
				chooseBtn.addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent e) {
						backupTo.setText(getBackUpPath());
					}
				});
				chooseBtn.setEnabled(false);
				retrieveDbBtn = new JButton("Verkrijg Databases");
				retrieveDbBtn.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent arg0) {
						do{
							getDatabases(username.getText(), password.getText(),databaseUrl.getText(),databasePort.getText());
						}
						while(counter==0);
						
						if(counter == 1 && con != null){
							lblDb.setEnabled(true);
							cb.setEnabled(true);
							chooseBtn.setEnabled(true);
							lblBackupTo.setEnabled(true);
							backupTo.setEnabled(true);
							retrieveDbBtn.setEnabled(false);
						}
					}
				});
				backupBtn = new JButton("Backup Database");
				
			//Enabled = False
			cb.setEnabled(false);
				
			//Toevoegen aan getDataPanel
			getData.add(lblUname);
			getData.add(username,"wrap");
			getData.add(lblPasswd);
			getData.add(password,"wrap");
			getData.add(lblDburl);
			getData.add(databaseUrl);
			getData.add(retrieveDbBtn,"wrap");
			getData.add(lblDbPort);
			getData.add(databasePort,"wrap");
			getData.add(lblDb);
			getData.add(cb,"wrap");
			getData.add(lblBackupTo);
			getData.add(backupTo);
			getData.add(chooseBtn,"wrap");
			
			//BottomPanel
			backup = new JPanel(new FlowLayout(1));
		
			backupBtn = new JButton("Backup!");
			backupBtn.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent arg0) {
					if(arg0.getSource().equals(backupBtn)){
						String timeStamp1 = new SimpleDateFormat("ddMMyyyy_HHmmss").format(Calendar.getInstance().getTime());
						String timeStamp2 = new SimpleDateFormat("EEEE dd MMMM yyyy").format(Calendar.getInstance().getTime());
						String backuppath=backupTo.getText();
						String Database =SelectedDatabaseName;
						String host = databaseUrl.getText();
						String port = databasePort.getText();
						String Password =password.getText();
						String user=username.getText();
						   try
						   {
							   Backup b = new Backup();
							   //Zip maken van de database en de .sql van de backup erin zetten
							   byte[] data = b.getData(host, port, user, Password, Database).getBytes();
								   File filedst = new File(backuppath+"\\"+Database+"_"+timeStamp1+".zip");
								   FileOutputStream dest = new FileOutputStream(filedst);
								   ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(dest));
								   zip.setMethod(ZipOutputStream.DEFLATED);
								   zip.setLevel(Deflater.BEST_COMPRESSION);
								   zip.putNextEntry(new ZipEntry(Database+"_"+timeStamp1+".sql"));
								   //De String wat de method getData() returned wegschrijven
								   zip.write(data);
								   zip.close();
								   dest.close();
								   JOptionPane.showMessageDialog(null, "Er is een backup van "+Database+" gemaakt op "+timeStamp2,"Database BackUp Wizard",JOptionPane.INFORMATION_MESSAGE);
								   backupTo.setText("");
								   databaseUrl.setText("");
								   databasePort.setText("3306");
								   password.setText("");
								   username.setText("");
								   cb.removeAllItems();
								   lblDb.setEnabled(false);
								   cb.setEnabled(false);
								   chooseBtn.setEnabled(false);
								   lblBackupTo.setEnabled(false);
								   backupTo.setEnabled(false);
						   }
						   catch (Exception ex){
							   JOptionPane.showMessageDialog(null, "Kon geen backup maken van "+Database+" op "+timeStamp2,"Database BackUp Wizard",JOptionPane.INFORMATION_MESSAGE);
							   backupTo.setText("");
							   SelectedDatabaseName="";
							   databaseUrl.setText("");
							   databasePort.setText("");
							   password.setText("");
							   username.setText("");
							   cb.removeAll();
						   }
					}
				}
			});
			//backupButton toevoegen aan Jpanel
			backup.add(backupBtn);
			
		//Toevoegen aan het frame.
		add(getData,BorderLayout.CENTER);
		add(backup,BorderLayout.SOUTH);
	}
	
	/// <summary>
	/// Deze method verkrijg databases van de meegegeven DB server en zet deze in een combobox.
	/// </summary>
	/// <parameter name="username">Dit is de loginnaam om te connecten met de DB.</parameter>
	/// <parameter name="password">Dit is het wachtwoord om te connecten met de DB.</parameter>
	/// <parameter name="dbUrl">Dit is het IP van de database server.</parameter>
	/// <parameter name="dbPort">Dit is de poort van de database server.</parameter>
	/// <author>Flemming Bosch</author>
	public void getDatabases(String username,String password,String dbUrl,String dbPort){
		databasesAL = new ArrayList<String>();
		counter=1;
		
		try {
			Class.forName("com.mysql.jdbc.Driver");
			String DBURL = "jdbc:mysql://"+dbUrl+":"+dbPort+"/";
		    con = DriverManager.getConnection(DBURL,username,password);
		    DatabaseMetaData meta = con.getMetaData();
		    ResultSet res = meta.getCatalogs();
		    //zolang er databases zijn
		    while (res.next()){
			//databases toevoegen aan de lijst
		    	String database = res.getString("TABLE_CAT");
		    	databasesAL.add(database);
		    }
		    //ArrayList omzetten naar een String Array
		    linesArr = databasesAL.toArray(new String[databasesAL.size()]);
		    //De String Array doorlopen en toevoegen aan de combobox.
		    for(int i=0; i< linesArr.length;i++){
		    	cb.addItem(linesArr[i].toString());
		    }
		    //resultset sluiten
		    res.close();
		    //connectie sluiten 
		    con.close();
		} 
		catch (SQLException e) {
			JOptionPane.showMessageDialog(this,"Kon geen verbinding maken met de database server!","Verbinding met de database server mislukt!",JOptionPane.ERROR_MESSAGE);
		    //System.err.println("SQLException: "+e.getMessage());
		} catch (ClassNotFoundException e) {
			System.err.println("ClassException: "+e.getMessage());
		}
	}
	
	/// <summary>
	/// Deze method verkrijgt het path waar de database opgeslagen moet worden.
	/// </summary>
	/// <author>Flemming Bosch</author>
	public static String getBackUpPath() {
		String backUpPath = "";
        JFileChooser fc = null;

        if (fc == null) {
        	fc = new JFileChooser();
            fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            fc.setAcceptAllFileFilterUsed(false);
        }
        int returnVal = fc.showDialog(null, "Selecteer");
        if (returnVal == JFileChooser.APPROVE_OPTION) {
        	File file = fc.getSelectedFile();
        	backUpPath = file.getAbsolutePath();
        }
        
        //BackupPath
        return backUpPath;
	}
}